package com.ultron.app.component.excel;



import com.ultron.app.util.Func;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 实体处理工具
 */
public class ColumnUtil {
    private static final CacheUtil<List<Field>, Object> cacheUtil = new CacheUtil<>();
    private static final CacheUtil<List<Field>, Object> annUtil = new CacheUtil<>();

    public static <T> List<Field> getFields(Class<T> tClass) {
        if (cacheUtil.getValue(tClass) != null) {
            return cacheUtil.getValue(tClass);
        }
        List<Field> fields = new ArrayList<>();
        if (tClass.getSuperclass() != null) {
            fields.addAll(Arrays.asList(tClass.getSuperclass().getDeclaredFields()));
            if (tClass.getSuperclass().getSuperclass() != null) {
                fields.addAll(Arrays.asList(tClass.getSuperclass().getSuperclass().getDeclaredFields()));
            }
        }
        fields.addAll(Arrays.asList(tClass.getDeclaredFields()));
        cacheUtil.updateValue(tClass, fields);
        return fields;
    }

    public static <T> List<Field> getFieldsByAnn(Class<T> tClass, Class<? extends Annotation> aClass) {
        if (annUtil.getValue(tClass) != null) {
            return annUtil.getValue(tClass);
        }
        List<Field> collect = getFields(tClass).stream().filter(f ->
                f.isAnnotationPresent(aClass)
        ).collect(Collectors.toList());
        annUtil.updateValue(tClass, collect);
        return collect;
    }

    /**
     * 得到某个属性的值。
     *
     * @param t
     * @param filedName
     * @param <T>
     * @return
     */
    public static <T> String getFieldString(T t, String filedName) {
        List<Field> fields = getFields(t.getClass());
        for (Field f : fields) {
            if (f.getName().equals(filedName)) {
                try {
                    boolean b = f.isAccessible();
                    f.setAccessible(true);
                    Object o = f.get(t);
                    f.setAccessible(b);
                    if (o != null) {
                        return o.toString();
                    } else {
                        return null;
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }


    /**
     * 获取值。
     *
     * @param t
     * @param ft
     * @param <T>
     * @return
     */
    public static <T> Object getFieldVal(T t, String ft) {
        if (Func.isEmpty(t) || Func.isEmpty(ft)) {
            return null;
        }
        try {
            Field f = getField(t.getClass(), ft);
            if (f == null) {
                return null;
            }
            boolean b = f.isAccessible();
            f.setAccessible(true);
            Object o = f.get(t);
            f.setAccessible(b);
            return o;
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return null;
    }

    public static Field getField(Class<?> aClass, String ft) {
        Optional<Field> first = getFields(aClass).stream().filter(f -> f.getName().equals(ft)).findFirst();
        return first.orElse(null);
    }


    public static void setFieldNull(Object obj, String ft) {
        try {
            Field f = getField(obj.getClass(), ft);
            boolean b = f.isAccessible();
            f.setAccessible(true);
            f.set(obj, null);
            f.setAccessible(b);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}
